/**
 * 检测类型
 * @param {any} target 检测的目标
 * @returns {'string'|'number'|'array'|'object'|'function'|'null'|'undefined'|'regexp'} 只枚举一些常用的类型
 */
function checkType(target) {
  /** @type {string} */
  const value = Object.prototype.toString.call(target);
  const result = value.match(/\[object (\S*)\]/)[1];
  return result.toLocaleLowerCase();
}

/**
 * 通过`Blob`对象信息将文件保存到本地
 * @param {object} params
 * @param {Blob} params.blob new Blob([xxx])
 * @param {string} params.filename 文件名
 * @param {() => void} params.success 保存成功回调
 * @param {(tip: string) => void} params.fail 保存失败回调
 */
function saveFileByBlob(params) {
  const URL = window.URL || window.webkitURL;
  if ('download' in document.createElement('a')) {
    const label = document.createElement('a');
    label.download = params.filename;
    label.style.display = 'none';
    label.href = URL.createObjectURL(params.blob);
    document.body.appendChild(label);
    label.click();
    URL.revokeObjectURL(label.href);
    document.body.removeChild(label);
    checkType(params.success) === 'function' && params.success();
  } else if (navigator.msSaveBlob) {
    navigator.msSaveBlob(params.blob, params.filename);
    checkType(params.success) === 'function' && params.success();
  } else {
    checkType(params.fail) === 'function' && params.fail();
  }
}

/**
 * 通过图片地址将文件保存到本地
 * @param {object} params
 * @param {string} params.url 文件地址（前提是这个图片允许跨域请求）
 * @param {string} params.filename 文件名
 * @param {() => void} params.success 加载成功回调
 * @param {(tip: string) => void} params.fail 加载失败回调
 */
function saveFileByLink(params) {
  const XHR = new XMLHttpRequest();
  XHR.open('get', params.url, true);
  XHR.responseType = 'blob';
  XHR.setRequestHeader("Cache-Control", "no-cache");
  XHR.onreadystatechange = function () {
    if (XHR.readyState !== 4) return;
    if (XHR.status === 200 || XHR.status === 304) {
      const data = XHR.response;
      const blob = new Blob([data]);
      saveFileByBlob({
        blob,
        ...params
      })
    } else {
      checkType(params.fail) === 'function' && params.fail('图片加载失败');
    }
  }
  XHR.send();
}